package com.lj.infoisland.util;

import java.util.*;

public class WeightedJaccardSimilarity {
    public static void main(String[] args) {
        // 示例数据
        Map<String, Set<Integer>> userInterests = new HashMap<>();
        userInterests.put("user1", new HashSet<>(Arrays.asList(1, 2, 3, 4, 5, 6)));
        userInterests.put("user2", new HashSet<>(Arrays.asList(2, 3, 5, 7, 8, 9)));
        userInterests.put("user3", new HashSet<>(Arrays.asList(1, 4, 5, 6, 7, 10)));
        userInterests.put("user4", new HashSet<>(Arrays.asList(1, 2, 3, 6, 11, 12)));
        userInterests.put("user5", new HashSet<>(Arrays.asList(1, 3, 4, 5, 7, 8)));
        userInterests.put("user6", new HashSet<>(Arrays.asList(1, 4, 6, 8, 10, 12)));
        userInterests.put("user7", new HashSet<>(Arrays.asList(1, 2, 3, 5, 9, 10)));
        userInterests.put("user8", new HashSet<>(Arrays.asList(1, 2, 4, 6, 8, 10)));
        userInterests.put("user9", new HashSet<>(Arrays.asList(2, 3, 5, 7, 9, 11)));
        userInterests.put("user10", new HashSet<>(Arrays.asList(1, 3, 5, 7, 9, 11)));
        userInterests.put("user11", new HashSet<>(Arrays.asList(2, 4, 6, 8, 10, 12)));
        userInterests.put("user12", new HashSet<>(Arrays.asList(1, 3, 4, 6, 8, 12)));

        // 权重列表，前面的标签权重更大
        Map<Integer, Double> weights = new HashMap<>();
        weights.put(1, 0.6);
        weights.put(2, 0.28);
        weights.put(3, 0.16);
        weights.put(4, 0.08);
        weights.put(5, 0.05);
        weights.put(6, 0.04);

        // 当前用户
        String currentUser = "user1";

        // 找到与当前用户兴趣最相似的前十个用户
        List<String> mostSimilarUsers = findMostSimilarUsers(currentUser, userInterests, weights, 10);
        System.out.println("与 " + currentUser + " 兴趣最相似的前十个用户是: " + mostSimilarUsers);
    }

    // 计算两个集合的加权Jaccard相似系数
    private static double weightedJaccardSimilarity(Set<Integer> set1, Set<Integer> set2, Map<Integer, Double> weights) {
        double intersectionWeight = 0.0;
        double unionWeight = 0.0;

        Set<Integer> unionSet = new HashSet<>(set1);
        unionSet.addAll(set2);

        for (Integer element : unionSet) {
            double weight = weights.getOrDefault(element, 1.0); // 如果标签没有指定权重，默认权重为1.0
            if (set1.contains(element) && set2.contains(element)) {
                intersectionWeight += weight;
            }
            unionWeight += weight;
        }

        return intersectionWeight / unionWeight;
    }

    // 找到与当前用户兴趣最相似的前N个用户
    private static List<String> findMostSimilarUsers(String currentUser, Map<String, Set<Integer>> userInterests, Map<Integer, Double> weights, int topN) {
        List<Map.Entry<String, Double>> similarityList = new ArrayList<>();
        Set<Integer> currentUserInterests = userInterests.get(currentUser);

        for (Map.Entry<String, Set<Integer>> entry : userInterests.entrySet()) {
            String user = entry.getKey();
            Set<Integer> interests = entry.getValue();

            if (!user.equals(currentUser)) {
                double similarity = weightedJaccardSimilarity(currentUserInterests, interests, weights);
                similarityList.add(new AbstractMap.SimpleEntry<>(user, similarity));
            }
        }

        similarityList.sort((a, b) -> Double.compare(b.getValue(), a.getValue()));

        List<String> mostSimilarUsers = new ArrayList<>();
        for (int i = 0; i < Math.min(topN, similarityList.size()); i++) {
            mostSimilarUsers.add(similarityList.get(i).getKey());
        }

        return mostSimilarUsers;
    }
}